using System;
using System.IO;
using System.Net;
using System.Text;
namespace Whitepages
{
    public class Web
    {
        /// <summary>
        /// Generic HTTP String Reader
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="Data"></param>
        /// <param name="Username"></param>
        /// <param name="Password"></param>
        /// <param name="Domain"></param>
        /// <param name="ProxyAddress"></param>
        /// <param name="ProxyPort"></param>
        /// <param name="DoPOST"></param>
        /// <returns></returns>
        public static string HTTPAsString(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, bool DoPOST)
        {
            return System.Text.ASCIIEncoding.ASCII.GetString(HTTPAsBytes(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, DoPOST));
        }

        public static string HTTPAsString(string URL)
        {
            return HTTPAsString(URL, null, "", "", "", "", 0, false);
        }
        public static System.Net.WebResponse HTTPAsWebResponse(string URL)
        {
            return HTTPAsWebResponse(URL, null, "", "", "", "", 0, false);
        }
        public static System.Net.WebResponse HTTPAsWebResponse(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, bool DoPOST)
        {
            if (!DoPOST && Data != null && Data.Length > 0)
            {
                string restoftheurl = System.Text.ASCIIEncoding.ASCII.GetString(Data);
                if (URL.IndexOf("?") <= 0) URL = URL + "?";
                URL = URL + restoftheurl;
            }
            System.Net.WebRequest wreq = System.Net.HttpWebRequest.Create(URL);
            wreq.Method = "GET";
            if (DoPOST) wreq.Method = "POST";
            if (ProxyAddress != null && ProxyAddress.Trim() != "" && ProxyPort > 0)
            {
                WebProxy webProxy = new WebProxy(ProxyAddress, ProxyPort);
                webProxy.BypassProxyOnLocal = true;
                wreq.Proxy = webProxy;
            }
            else
            {
                wreq.Proxy = WebProxy.GetDefaultProxy();
            }
            if (Username != null && Password != null && Domain != null && Username.Trim() != "" && Password.Trim() != null && Domain.Trim() != null)
                wreq.Credentials = new System.Net.NetworkCredential(Username, Password, Domain);
            else if (Username != null && Password != null && Username.Trim() != "" && Password.Trim() != null)
                wreq.Credentials = new System.Net.NetworkCredential(Username, Password);

            if (DoPOST && Data != null && Data.Length > 0)
            {
                wreq.ContentType = "application/x-www-form-urlencoded";
                System.IO.Stream request = wreq.GetRequestStream();
                request.Write(Data, 0, Data.Length);
                request.Close();
            }
            WebResponse wrsp = wreq.GetResponse();
            return wrsp;
        }

        /// <summary>
        /// its a default of 1024 bytes for the buffer because of download speeds and such
        /// some arbritray number which to buffer the downloaded content
        /// too high of a number and the responsestream cant keep up
        /// too low and the more loops, and ore time it takes to get the content
        /// if your constantly tearing the same URL down you may want to test 
        /// with different buffersizes for optimal performance
        /// with my tests 1024 (1kb/s) was optimal for text and binary data
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public static int BufferSize = 1024;
        public static byte[] ConvertWebResponseToByteArray(System.Net.WebResponse res)
        {
            System.IO.BinaryReader br = new BinaryReader(res.GetResponseStream());
            //download and buffer the binary stream into a memory stream
            System.IO.MemoryStream stm = new MemoryStream();
            int pos = 0;
            int maxread = BufferSize;
            while (true)
            {
                byte[] content = br.ReadBytes(maxread);
                if (content.Length <= 0) break;
                if (content.Length < maxread) maxread = maxread - content.Length;
                stm.Write(content, 0, content.Length);
                pos += content.Length;
            }
            br.Close();
            stm.Position = 0;
            byte[] final = new byte[(int)stm.Length];
            stm.Read(final, 0, final.Length);
            stm.Close();
            return final;
        }
        /// <summary>
        /// Generic HTTP Byte Array Reader
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="Data"></param>
        /// <param name="Username"></param>
        /// <param name="Password"></param>
        /// <param name="Domain"></param>
        /// <param name="ProxyAddress"></param>
        /// <param name="ProxyPort"></param>
        /// <param name="DoPOST"></param>
        /// <returns></returns>
        public static byte[] HTTPAsBytes(string URL, byte[] Data, string Username, string Password, string Domain, string ProxyAddress, int ProxyPort, bool DoPOST)
        {
            System.Net.WebResponse res = HTTPAsWebResponse(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, DoPOST);
            return ConvertWebResponseToByteArray(res);
        }
        public static byte[] HTTPAsBytes(string URL)
        {
            return HTTPAsBytes(URL, null, "", "", "", "", 0, false);
        }
        /// <summary>
        /// Save content at any URL to disk, either with a POST or a GET
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="Data"></param>
        /// <param name="Username"></param>
        /// <param name="Password"></param>
        /// <param name="Domain"></param>
        /// <param name="Filename"></param>
        /// <param name="ProxyAddress"></param>
        /// <param name="ProxyPort"></param>
        /// <param name="DoPost"></param>
        /// <returns></returns>
        public static bool SaveHTTPToFile(string URL, byte[] Data, string Username, string Password, string Domain, string Filename, string ProxyAddress, int ProxyPort, bool DoPost)
        {
            byte[] data = HTTPAsBytes(URL, Data, Username, Password, Domain, ProxyAddress, ProxyPort, DoPost);
            if (data != null)
            {
                System.IO.FileStream fs = new FileStream(Filename, System.IO.FileMode.Create);
                fs.Write(data, 0, data.Length);
                fs.Close();
                return true;
            }
            return false;
        }

        public static bool SaveHTTPToFile(string URL, string Filename)
        {
            return SaveHTTPToFile(URL, null, "", "", "", Filename, "", 0, false);
        }
        /// <summary>
        /// Upload content to HTTP
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="Username"></param>
        /// <param name="Password"></param>
        /// <param name="Domain"></param>
        /// <param name="Filename"></param>
        /// <param name="ProxyAddress"></param>
        /// <param name="ProxyPort"></param>
        /// <param name="DoPost"></param>
        /// <returns></returns>
        public static bool SendFileToHTTP(string URL, string Username, string Password, string Domain, string Filename, string ProxyAddress, int ProxyPort, bool DoPost)
        {
            if (!System.IO.File.Exists(Filename)) return false;
            System.IO.FileStream fs = new FileStream(Filename, System.IO.FileMode.Open);
            byte[] d = new byte[(int)fs.Length];
            fs.Read(d, 0, d.Length);
            fs.Close();
            if (d != null)
            {
                HTTPAsBytes(URL, d, Username, Password, Domain, ProxyAddress, ProxyPort, DoPost);
                return true;
            }
            else
            {
                return false;
            }
        }

        #region URLEncode Functions.  I had having to set a reference to System.Web just for this.  Silly mistake...
        public static string UrlEncode(string s)
        {
            Encoding e = Encoding.Default;
            return UrlEncode(s, e);
        }

        public static string UrlEncode(string str, Encoding e)
        {
            if (str == null)
            {
                return null;
            }
            return Encoding.ASCII.GetString(UrlEncodeToBytes(str, e));

        }
        public static byte[] UrlEncodeToBytes(string str, Encoding e)
        {
            if (str == null)
            {
                return null;
            }
            byte[] bytes = e.GetBytes(str);
            return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
        }
        internal static char IntToHex(int n)
        {
            if (n <= 9)
            {
                return (char)(n + 0x30);
            }
            return (char)((n - 10) + 0x61);
        }


        internal static bool IsSafe(char ch)
        {
            if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || ((ch >= '0') && (ch <= '9')))
            {
                return true;
            }
            switch (ch)
            {
                case '\'':
                case '(':
                case ')':
                case '*':
                case '-':
                case '.':
                case '_':
                case '!':
                    return true;
            }
            return false;
        }

        private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue)
        {
            int num = 0;
            int num2 = 0;
            for (int i = 0; i < count; i++)
            {
                char ch = (char)bytes[offset + i];
                if (ch == ' ')
                {
                    num++;
                }
                else if (!IsSafe(ch))
                {
                    num2++;
                }
            }
            if ((!alwaysCreateReturnValue && (num == 0)) && (num2 == 0))
            {
                return bytes;
            }
            byte[] buffer = new byte[count + (num2 * 2)];
            int num4 = 0;
            for (int j = 0; j < count; j++)
            {
                byte num6 = bytes[offset + j];
                char ch2 = (char)num6;
                if (IsSafe(ch2))
                {
                    buffer[num4++] = num6;
                }
                else if (ch2 == ' ')
                {
                    buffer[num4++] = 0x2b;
                }
                else
                {
                    buffer[num4++] = 0x25;
                    buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15);
                    buffer[num4++] = (byte)IntToHex(num6 & 15);
                }
            }
            return buffer;
        }

        #endregion

    }
}
